using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using FlatRedBall;
using FlatRedBall.Graphics;
using FlatRedBall.Math.Geometry;
using FlatRedBall.Input;

using Microsoft.Xna.Framework;
using Microsoft.Devices;

using Xzipit.Utilities;
using Xzipit.Interfaces;
using Microsoft.Xna.Framework.Audio;
using Xzipit.Utilities.Gestures;

namespace Xzipit.MenuObjects
{
    class WinBox : MenuObject
    {
        #region Fields

        private Text _time;
        private Text _rewardText;
        private Sprite _reward;
        private Sprite _winBox;
        private Sprite _timeBox;

        private bool _winSoundPlay;
        private bool _timeSoundPlay;
        private bool _time2SoundPlay;
        private bool _nextSoundPlay;

        private double _timer;

        private AxisAlignedRectangle _menuCollision;
        private AxisAlignedRectangle _nextCollision;

        // Keep the ContentManager for easy access:
        string _contentManagerName;

        protected SoundEffect _sewingSound;
        protected SoundEffect _sewingSound2;

        private Circle _collision;

        #endregion

        #region Properties
        // All properties of Button are already covered in Obstacle.
        public bool Visible
        {
            get;
            set;
        }

        public override float Alpha
        {
            set
            {
                _rewardText.Alpha = value;
                _winBox.Alpha = value;
                _timeBox.Alpha = value;
                _time.Alpha = value;
                _sprite.Alpha = value;
                _reward.Alpha = value;
            }
        }

        public override float AlphaRate
        {
            set
            {
                _rewardText.AlphaRate = value;
                _winBox.AlphaRate = value;
                _timeBox.AlphaRate = value;
                _time.AlphaRate = value;
                _sprite.AlphaRate = value;
                _reward.AlphaRate = value;
            }
        }

        public bool ToMenu
        {
            get;
            private set;
        }

        public bool ToNext
        {
            get;
            private set;
        }

        #endregion

        #region Methods

        // Constructor
        public WinBox(string contentManagerName)
        {
            // Set the ContentManagerName and call Initialize:
            _contentManagerName = contentManagerName;

            // If you don't want to add to managers, make an overriding constructor
            Initialize(true);
        }

        protected override void Initialize(bool addToManagers)
        {
            // Here you can preload any content you will be using
            // like .scnx files or texture files.
            Visible = false;
            ToMenu = false;
            ToNext = false;
            ToWorld = false;

            if (addToManagers)
            {
                AddToManagers(null);
            }
        }

        public override void AddToManagers(Layer layerToAddTo)
        {
            // Add the Entity to the SpriteManager
            // so it gets managed properly (velocity, acceleration, attachments, etc.)
            SpriteManager.AddPositionedObject(this);

            // you win component
            _winBox = SpriteManager.AddSprite(@"Content\MenuObjects\WinBox\win", _contentManagerName);
            _winBox.AttachTo(this, false);
            _winBox.RelativeY = 5.0f;
            _winBox.Alpha = 0.0f;

            _winBox.PixelScale();

            // time component
            _timeBox = SpriteManager.AddSprite(@"Content\MenuObjects\WinBox\time", _contentManagerName);
            _timeBox.AttachTo(this, false);
            _timeBox.Alpha = 0.0f;

            _timeBox.PixelScale();

            // options component
            _sprite = SpriteManager.AddSprite(@"Content\MenuObjects\WinBox\option", _contentManagerName);
            _sprite.AttachTo(this, false);
            _sprite.RelativeY = -6.0f;
            _sprite.Alpha = 0.0f;

            _sprite.PixelScale();

            _time = TextManager.AddText("", GameProperties.CustomFont);
            _time.Scale = GameProperties.TIME_SCALE;
            _time.Spacing = GameProperties.TIME_SCALE;
            _time.SetColor(0.0f, 0.0f, 0.0f);
            _time.AttachTo(_timeBox, false);
            _time.RelativeX = -1.2f;
            _time.RelativeY = 0.0f;
            _time.RelativeZ = 0.1f;
            _time.Alpha = 0.0f;

            _rewardText = TextManager.AddText("", GameProperties.CustomFont);
            _rewardText.Scale = 0.8f;
            _rewardText.Spacing = 0.9f;
            _rewardText.SetColor(0.0f, 0.0f, 0.0f);
            _rewardText.AttachTo(_timeBox, false);
            _rewardText.RelativeX = -1.2f;
            _rewardText.RelativeY = -1.5f;
            _rewardText.RelativeZ = 0.1f;
            _rewardText.Alpha = 0.0f;

            _reward = SpriteManager.AddSprite(GameProperties.GetPins());
            _reward.AttachTo(_timeBox, false);
            _reward.Animate = false;
            _reward.CurrentFrameIndex = 0;
            _reward.RelativeX = -3.0f;
            _reward.RelativeY = -1.0f;
            _reward.ScaleX = 1.5f;
            _reward.ScaleY = 1.5f;
            _reward.RelativeZ = 40.0f;
            _reward.UseAnimationRelativePosition = false;

            // the box collision
            _collision = ShapeManager.AddCircle();
            _collision.AttachTo(_sprite, false);
            _collision.Radius = _sprite.ScaleX;
            _collision.Visible = false;
            _collision.RelativeX = 0.0f;
            _collision.RelativeY = 0.0f;

            // the menu button collision
            _menuCollision = ShapeManager.AddAxisAlignedRectangle();
            _menuCollision.AttachTo(_sprite, false);
            _menuCollision.ScaleX = 58 / _sprite.PixelPerUnit();
            _menuCollision.ScaleY = 58 / _sprite.PixelPerUnit();
            _menuCollision.Visible = false;
            _menuCollision.RelativeX = -3.0f;
            _menuCollision.RelativeY = 0.0f;

            // the next button collision
            _nextCollision = ShapeManager.AddAxisAlignedRectangle();
            _nextCollision.AttachTo(_sprite, false);
            _nextCollision.ScaleX = 58 / _sprite.PixelPerUnit();
            _nextCollision.ScaleY = 58 / _sprite.PixelPerUnit();
            _nextCollision.Visible = false;
            _nextCollision.RelativeX = 3.0f;
            _nextCollision.RelativeY = 0.0f;

            _enabled = false;

            _touchSound = FlatRedBallServices.Load<SoundEffect>(@"Content\Sound\button");
            _sewingSound = FlatRedBallServices.Load<SoundEffect>(@"Content\Sound\sewing");
            _sewingSound2 = FlatRedBallServices.Load<SoundEffect>(@"Content\Sound\timesewing");

            _timer = 0;
            _time2SoundPlay = false;
            _timeSoundPlay = false;
            _winSoundPlay = false;
            _nextSoundPlay = false;
        }

        public override void Activity()
        {
            if (Visible)
            {
                foreach (GameGesture g in GameGestureManager.Gestures)
                {
                    if (WasTapped(g))
                    {
                        OnTap(g.End);
                        break;
                    }
                }

                if (_enabled)
                {
                    SetAllVisible(); 
                    return;
                }
                else if (_winBox.Alpha < 1.0 && !_winSoundPlay)
                {
                    this.AlphaRate = 0.0f;
                    _reward.Alpha = 1.0f;
                    _reward.RelativeZ = 40.0f;
                    _reward.AlphaRate = 0.0f;
                    _winBox.AlphaRate = 1.5f;
                    _sewingSound.PlaySound();
                    _winSoundPlay = true;
                }
                else if (_winBox.Alpha >= 1.0)
                {
                    _winBox.AlphaRate = 0.0f;
                }

                if (_timeBox.Alpha < 1.0 && !_timeSoundPlay && TimeManager.CurrentTime - _timer > 0.9f)
                {
                    _timeBox.AlphaRate = 1.5f;
                    _sewingSound.PlaySound();
                    _timeSoundPlay = true;
                }
                else if (_timeBox.Alpha >= 1.0 && !_time2SoundPlay)
                {
                    _timeBox.AlphaRate = 0.0f;
                    _time.AlphaRate = 3.0f;
                    _sewingSound2.PlaySound();
                    _time2SoundPlay = true;
                }
                else if (_time.Alpha >= 1.0 && _reward.RelativeZ == 40.0f)
                {
                    _time.AlphaRate = 0.0f;
                    _sewingSound2.PlaySound();
                    _rewardText.AlphaRate = 3.0f;
                    
                    _reward.RelativeZVelocity = -50.0f;
                }
                else if (_reward.RelativeZ <= 0.0f)
                {
                    _reward.RelativeZ = 0.1f;
                    _rewardText.AlphaRate = 0.0f;
                }

                if (_sprite.Alpha < 1.0f && !_nextSoundPlay && TimeManager.CurrentTime - _timer > 2.5f)
                {
                    _sprite.AlphaRate = 1.5f;
                    _sewingSound.PlaySound();
                    _nextSoundPlay = true;
                }
                else if (_sprite.Alpha >= 0.6)
                {
                    _enabled = true;
                }
            }
        }

        public void Display(double elapsedTime, List<double> targetTimes)
        {
            int pinNum = 4;
            _time.DisplayText = elapsedTime.ToTimeString();
            if (elapsedTime < targetTimes[0])
            {
                pinNum = 0;

                _reward.CurrentFrameIndex = pinNum;
                _rewardText.DisplayText = "Gold!";
            }
            else if (elapsedTime < targetTimes[1])
            {
                pinNum = 1;

                _reward.CurrentFrameIndex = pinNum;
                _rewardText.DisplayText = "Silver!";
            }
            else if (elapsedTime < targetTimes[2])
            {
                pinNum = 2;

                _reward.CurrentFrameIndex = pinNum;
                _rewardText.DisplayText = "Bronze!";
            }
            else
            {
                pinNum = 3;

                _reward.CurrentFrameIndex = pinNum;
                _rewardText.DisplayText = "Iron!";
            }

            GameProperties.Save.SaveData(GameProperties.SelectedLevel,
                                         GameProperties.SelectedWorld, elapsedTime,
                                         pinNum);

            _timer = TimeManager.CurrentTime;
            Visible = true;
        }

        public void Reset()
        {
            FadeOut();
            
            _enabled = false;

            _reward.RelativeZ = 40.0f;
            _reward.RelativeVelocity = Vector3.Zero;

            _winSoundPlay = false;
            _timeSoundPlay = false;
            _time2SoundPlay = false;
            _nextSoundPlay = false;

            ToMenu = false;
            ToNext = false;
        }

        public override void Destroy()
        {
            base.Destroy();

            ShapeManager.Remove(_nextCollision);
            ShapeManager.Remove(_menuCollision);
            ShapeManager.Remove(_collision);
            TextManager.RemoveText(_time);
            TextManager.RemoveText(_rewardText);
            SpriteManager.RemoveSprite(_reward);
            SpriteManager.RemoveSprite(_winBox);
            SpriteManager.RemoveSprite(_timeBox);
        }

        #endregion

        #region Fade

        public void FadeOut()
        {
            this.AlphaRate = -GameProperties.ALPHA_RATE;
        }

        #endregion

        #region Private Methods
        private void SetAllVisible()
        {
            this.Alpha = 1.0f;
            this.AlphaRate = 0.0f;

            _reward.RelativeZ = 0.1f;
            _reward.RelativeVelocity = Vector3.Zero;
            _enabled = true;
        }

        #region Gesture Management
        private bool WasTapped(GameGesture g)
        {
            return (g.GameGestureType == GameGestureType.Tap);
        }

        private void OnTap(Vector3 touchPosition)
        {
            if (_enabled)
            {
                // checks to see if the menu button is tapped.
                if (_menuCollision.IsPointInside(touchPosition.X, touchPosition.Y))
                {
                    ToMenu = true;
                    _touchSound.PlaySound();
                    VibrateController.Default.Start(TimeSpan.FromSeconds(.05));
                }

                // checks to see if the menu button is tapped.
                if (_nextCollision.IsPointInside(touchPosition.X, touchPosition.Y))
                {
                    VibrateController.Default.Start(TimeSpan.FromSeconds(.05));
                    _touchSound.PlaySound();
                    if (GameProperties.SelectedLevel < GameProperties.LEVELS_PER_WORLD)
                    {
                        ToNext = true;
                    }
                    else
                    {
                        if (GameProperties.SelectedWorld < GameProperties.TOTAL_WORLDS)
                        {
                            GameProperties.SelectedWorld++;
                            ToWorld = true;
                        }
                        else
                            ToMenu = true;
                    }
                }
            }
            else
            {
                _enabled = true;
            }

        }

        #endregion
        #endregion

        public bool ToWorld { get; set; }
    }
}
